extends Block

var grinder_enabled = false

var slowdown_factor = 3

const GRINDER_FREQ = 5
const GRINDER_SCALE_ANITIME = 0.1
var grinder_previous_pos = null

func _init():
	MOVE_ANITIME = 0.2
	print("Player initting")
	color = ColorN("white")

func _process(delta):
	if grinder_enabled:
		rotation = wrapf(rotation+2*PI*GRINDER_FREQ*delta,0,2*PI)
		var deletion_list = Array()
		var cur_pos = Vector2(_i,_j)
		var diff = cur_pos - grinder_previous_pos
		for b in Grid.Blocks:
			var b_pos = Vector2(b._i,b._j)
			var b_diff = b_pos - cur_pos
			if diff.x == 0:
				if b._i == _i and between(b._j, cur_pos.y, grinder_previous_pos.y):
					deletion_list.append(b)
			if diff.y == 0:
				if b._j == _j and between (b._i, cur_pos.x, grinder_previous_pos.x):
					deletion_list.append(b)

			if b_diff.length() < 0.98:
				deletion_list.append(b)
		for b in deletion_list:
			b.erase(true)


func between(target_a,b,c): # b and c can be in any order
	var mi= min(b,c)
	var ma= max(b,c)
	return (target_a <= ma and target_a > mi)

#func between(target_a,b,c): # b and c can be in any order
#	return (target_a == wrapf(target_a,a<ma and a>mi)

func plunge():

	_prepare_action()
	moving_sound()
	var height_to_surface = 0
	var height_to_groundline = abs(_j)

	print ("ground is ", height_to_groundline, " away")
	for j in range(height_to_groundline+1):
		if Grid.get_block(_i,_j-sign(_j)*j):
			height_to_surface = j-2
			break
	var wing = height_to_surface
	if height_to_surface >= 0:
		print ("wing is", wing)
		var targets = Array()
		for i in range(_i-wing,_i+wing+1):
			print ("checking",i)
			for block in Grid.Blocks:
				if block._i == i:
					targets.append(block)

		if len(targets)!=0:
			var target_bb = Grid.get_bb(targets)
			var target_height_above_ground = target_bb.max_j + 1
			if _j < 0:
				target_height_above_ground = -target_bb.min_j + 1
			print("target_height = ", target_height_above_ground)

			var initial_j = _j
			var ani_progress = 0

			move_to(_i,sign(_j),0,MOVE_ANITIME, Tween.EASE_IN)
			ani_progress+=MOVE_ANITIME
			Grid.translate_block(targets,0,-sign(_j)*(target_height_above_ground+1),ani_progress)
			execute_after(ani_progress,"plunge_bounce_down")
			ani_progress+=BLOCK_MOVE_ANITIME
			execute_after(ani_progress,"plunge_bounce_back", targets)

			Grid.patch_ground_hole(target_bb.min_i,target_bb.max_i,ani_progress)

			ani_progress+=BLOCK_MOVE_ANITIME

			execute_after(ani_progress, "check_height")

			ignore_input_for(ani_progress)


		else:
			move_to(_i,sign(_j),0,MOVE_ANITIME, Tween.EASE_IN)

func check_height():
	Grid.check_height()

func plunge_bounce_down():
	print("plunge_down_sign", sign(_j)," ", _j)
	hitting_sound()
	move_to(_i,-sign(_j),0,BLOCK_MOVE_ANITIME, Tween.EASE_OUT)

func plunge_bounce_back(targets):
	move_to(_i,-sign(_j))
	Grid.translate_block(targets,0,-sign(_j))

func drill():
	_prepare_action()
	moving_sound()
	enable_grinder()
	var targets = Array()
	for b in Grid.Blocks:
		if b._i == _i:
			targets.append(b)
	var bb = Grid.get_bb(targets)
	if bb:
		var dest_j = -1

		if _j >=0:
			dest_j = bb.min_j-1

		else:
			dest_j = bb.max_j+1

		if abs (dest_j) > Grid.MAX_Y:
			dest_j = sign(dest_j)*Grid.MAX_Y

		move_to(_i,dest_j)

	else:
		move_to(_i, -sign(_j))

	execute_after(MOVE_ANITIME,"disable_grinder")
	ignore_input_for(MOVE_ANITIME)

func roll(right = true):
	_prepare_action()
	moving_sound()

	var direction = 1 if right else -1
	var targets = Array()

	var j_below = _j - sign(_j)

	if Grid.get_block(_i,j_below):
		var length_forwards = Grid.check_x_continuity(_i,j_below,1)
		var length_backwards = Grid.check_x_continuity(_i,j_below,-1)

		for i in range(_i - length_backwards, _i + length_forwards+1):
			targets.append(Grid.get_block(i, j_below))

		for t in targets:
			if not (t._i + direction in range(Grid.BLOCKSX)):
				t.erase()
		Grid.translate_block(targets, direction, 0)

		if j_below == Grid.GROUND_LINE:
			if right and length_backwards == _i:
				Grid.add_trash(0,Grid.GROUND_LINE)
			if !right and length_forwards == Grid.BLOCKSX-1 - _i:
				Grid.add_trash(Grid.BLOCKSX-1,Grid.GROUND_LINE)

	var tw = SDTween.new()
	tw.interpolate_property(self,"rotation",rotation, rotation+direction*PI/2,BLOCK_MOVE_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_IN_OUT)
	add_child(tw)
	tw.start()

	ignore_input_for(BLOCK_MOVE_ANITIME)


func erase_layer(): #erases every block on a layer besides the one in is standing on

	_prepare_action()
	var prev_speed = MOVE_ANITIME
	MOVE_ANITIME *= slowdown_factor
	var ani_progress = 0
	enable_grinder()
	var move_targets = Array()
	for b in Grid.Blocks:
		if abs(b._j) > abs(_j) and sign(b._j) == sign(_j) and b._i != _i:
			move_targets.append(b)

	move_to(Grid.BLOCKSX-1,_j)

	slow_moving_sound()

	ani_progress+=MOVE_ANITIME

	execute_after(ani_progress,"erase_back")
	execute_after(ani_progress,"return_speed", prev_speed)
	ani_progress+=MOVE_ANITIME

	execute_after(ani_progress,"erase_return", _i)
	execute_after(ani_progress,"disable_grinder")
	if len(move_targets)!=0:
		execute_after(ani_progress,"erase_collapse", move_targets)
		ani_progress+=max(BLOCK_MOVE_ANITIME,prev_speed)
	else:
		ani_progress+=prev_speed

	ignore_input_for(ani_progress)

func erase_back():
	slow_moving_sound()
	move_to(0,_j)

func slow_moving_sound():
	var s = moving_sound()
	s.pitch_scale /= slowdown_factor
	s.volume_db+=1

func erase_return(initial_i):
	move_to(initial_i,_j)

func erase_collapse(targets):
	if len(targets)>=0:
		Grid.translate_block(targets,0,-sign(_j))

func reset():
	_prepare_action()
	Grid.onscreen_reset()
	ignore_input_for(BLOCK_MOVE_ANITIME)

func return_speed(prev_speed):
	MOVE_ANITIME = prev_speed

func enable_grinder():
	grinder_previous_pos = Vector2(_i,_j)
	var tw = SDTween.new()
	tw.interpolate_property(self,"scale",scale,scale/sqrt(2),GRINDER_SCALE_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_IN_OUT)
	add_child(tw)
	tw.start()
	grinder_enabled = true

func disable_grinder():
	grinder_enabled = false
	var tw = SDTween.new()
	tw.interpolate_property(self,"scale",scale,scale*sqrt(2),GRINDER_SCALE_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_IN_OUT)
	add_child(tw)
	tw.start()

	var tw2 = SDTween.new()
	tw2.interpolate_property(self,"rotation",rotation,0,GRINDER_SCALE_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_IN_OUT)
	add_child(tw2)
	tw2.start()

func hitting_sound():
	var p = SDRandPitch2D.new("res://sounds/pum2.ogg")
	add_child(p)
	p.play()

func moving_sound():
	var p = SDRandPitch2D.new("res://sounds/juh.ogg")
	add_child(p)
	p.play()
	return p

func _input(event):
	if event.is_action_pressed("erase_layer"):
		print("detecting input, player listening?",listening)
	if listening:
		var disabilities = Grid.Levels[Grid.current_level].disabled
		_prepare_action()
		if event.is_action_pressed("ui_up"):
			if not Grid.get_block(_i,_j+1):
				if abs(_j+1) <= Grid.MAX_Y:
					move_to(_i,_j+1 if not _j+1 == Grid.GROUND_LINE else _j+2)
					ignore_input_for(MOVE_ANITIME)
					moving_sound()

		if event.is_action_pressed("ui_down"):
			if not Grid.get_block(_i,_j-1):
				if abs(_j-1) <= Grid.MAX_Y:
					move_to(_i,_j-1 if not _j-1 == Grid.GROUND_LINE else _j-2)
					ignore_input_for(MOVE_ANITIME)
					moving_sound()

		if event.is_action_pressed("ui_right"):
			if not Grid.get_block(_i+1,_j):
				if _i+1 in range(Grid.BLOCKSX):
					move_to(_i+1,_j)
					ignore_input_for(MOVE_ANITIME)
					moving_sound()

		if event.is_action_pressed("ui_left"):
			if not Grid.get_block(_i-1,_j):
				if _i-1 in range(Grid.BLOCKSX):
					move_to(_i-1,_j)
					ignore_input_for(MOVE_ANITIME)
					moving_sound()

		if event.is_action_pressed("plunge"):
			if not "plunge" in disabilities:
				plunge()

		if event.is_action_pressed("drill"):
			if not "drill" in disabilities:
				drill()

		if event.is_action_pressed("erase_layer"):
			erase_layer()

		if event.is_action_pressed("roll_right"):
			if not "roll_right" in disabilities:
				roll(true)

		if event.is_action_pressed("roll_left"):
			if not "roll_left" in disabilities:
				roll(false)

		if event.is_action_pressed("ui_reset"):
			reset()

		if event.is_action_pressed("win"):
			Grid.win_stage()
